package com.logistics.utils.aspect.impl;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.logistics.account.service.AccountService;
import com.logistics.utils.bean.UserBean;
import com.logistics.utils.exception.MessageException;
import com.logistics.utils.tool.DateUtils;
import com.logistics.utils.tool.StringUtils;
import com.logistics.utils.tool.UserUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;

@Aspect
@Order(-1)
@Component
public class InsertAspect {

    @Autowired
    private UserUtils userUtils;

    @Autowired
    private AccountService accountService;

    @Pointcut("@annotation(com.logistics.utils.aspect.annotation.Insert)")
    public void listerInsert(){}


    @Before("listerInsert()")
    public void beforeInsert(JoinPoint point) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, JsonProcessingException, MessageException {
        Object object = point.getArgs().length > 0 ? point.getArgs()[0] : null;
        if(StringUtils.isNull(object)){
            return;
        }
        UserBean userBean = userUtils.getUserInfo();
        // 查询用户信息
        if(StringUtils.isNull(userBean)){
            if(StringUtils.isNotNull(object.getClass()) &&
                    StringUtils.isNotNull(object.getClass().getDeclaredMethod("getParameter"))){
                String parameter = (String) object.getClass().getDeclaredMethod("getParameter").invoke(object, null);
                JSONObject json = JSONObject.parseObject(parameter);
                if(StringUtils.isNotNull(json)){
                    Map<String, String> resMaps = accountService.codeByAccount(json.getString("account"));
                    if(StringUtils.isNotNull(resMaps)){
                        userBean = new UserBean();
                        userBean.setUserCode(resMaps.get("code"));
                        userBean.setOrganization(resMaps.get("organization"));
                        userBean.setDep(resMaps.get("dep"));
                    }
                }
            }
        }
        // 设置用户信息
        if(StringUtils.isNull(getMethodId(object)) || (StringUtils.isNotNull(getMethodId(object))
                && StringUtils.isNull(getMethodId(object).invoke(object , null)))){
            if(StringUtils.isNotNull(userBean)){
                setMethod(object, "setCreator", userBean.getUserCode(), String.class);
                setMethod(object, "setCreateOrgCode", userBean.getOrganization(), String.class);
                setMethod(object, "setCreateDepCode", userBean.getDep(), String.class);
            }
            setMethod(object, "setCreateTime", DateUtils.dateToStringFormat(new Date(),
                    DateUtils.YYYY_MM_DD_HH_MM_SS), String.class);
        }
        setMethod(object, "setUpdater", StringUtils.isNotNull(userBean) ? userBean.getUserCode() : "", String.class);
        setMethod(object, "setUpdateTime", DateUtils.dateToStringFormat(new Date(),
                DateUtils.YYYY_MM_DD_HH_MM_SS), String.class);
    }

    protected Method getMethodId(Object object){
        Method method = null;
        try {
            method = object.getClass().getDeclaredMethod("getId");
            method.setAccessible(true);
        } catch (NoSuchMethodException e) {
            return null;
        }
        return method;
    }

    protected Method getMethod(Class<?> cls, String methodName) throws NoSuchMethodException {
        return cls.getSuperclass().getMethod(methodName, null);
    }

    protected void setMethod(Object object, String methodName, Object value,Class type) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class<?> cls = object.getClass();
        Method method = cls.getSuperclass().getMethod(methodName, type);
        method.invoke(object, new Object[] { value });
    }
}
